from sqlalchemy.orm import DeclarativeBase
from flask import g

from app.utils.logger import logger
from app.utils.exceptions import InternalServerError, PermissionDeniedError


class Base(DeclarativeBase):
    __abstract__ = True

    # 抽象方法强制子类实现
    @classmethod
    def allow_fields(cls, user_role=None):
        """必须由子类定义允许访问的字段列表（抽象方法）"""
        raise NotImplementedError(f"{cls.__name__} 必须实现 allow_fields 属性")

    # 获取方法
    @classmethod
    def get_allow_fields(cls, user_role=None):
        """获取允许访问的字段"""
        return cls.allow_fields(user_role)

    @classmethod
    def validate_field(cls, field_name, operator_id=None, user_role=None, request=None):
        """
        验证字段是否允许访问
        使用方法：
        model_class.validate_field(field)  # 字段验证
        setattr(record, field, value)
        """
        allow_fields = cls.get_allow_fields(user_role)

        if field_name in allow_fields:
            return True

        log_details = {
            "model": cls.__name__,
            "attempted_field": field_name,
            "valid_fields": list(allow_fields),
            "operator_id": operator_id if operator_id else "unknown",
            "ip": request.remote_addr if request else "unknown",
            "endpoint": request.endpoint if request else "unknown"
        }

        logger.warning(
            "非法字段访问尝试",
            extra=log_details
        )

        raise PermissionDeniedError(f"{cls.__name__}.{field_name}", operator_id)


def get_class_by_tablename(tablename: str):
    """通过表名获取对应的 ORM 类"""
    # 获取所有已注册的类
    registry = Base.registry

    for mapper in registry.mappers:
        class_ = mapper.class_
        if hasattr(class_, '__tablename__') and class_.__tablename__ == tablename:
            return class_
    raise LookupError(f"表 {tablename} 未注册")
